﻿#include "pageCache.h"

pageCache pageCache::_pInit;

span* pageCache::fetchOfPage(size_t k) {
	// 申请大于128页span
	if (k > MAX_PAGE - 1) {
		//span* newSpan = new span;
		span* newSpan = _pool.myNew();
		void* ptr = systemAlloc(k);
		newSpan->_pageId = (PAGE_T)ptr >> PAGE_SHIFT;
		newSpan->_n = (k);

		//_idMap[newSpan->_pageId] = newSpan;
		_idMap.set(newSpan->_pageId, newSpan);

		return newSpan;
	}

	// 先检查第k个桶有没有span
	if (!_pageSpanList[k].empty()) {
		auto frontSpan = _pageSpanList[k].popFront();
		for (PAGE_T i = 0; i < k; ++i) {
			//_idMap[frontSpan->_pageId + i] = frontSpan;
			_idMap.set(frontSpan->_pageId + i, frontSpan);
		}
		return frontSpan;
	}

	// 没有就往后查有span的桶，进行切割
	for (size_t i = k + 1; i < MAX_PAGE; ++i) {
		if (!_pageSpanList[i].empty()) {
			span* nSpan = _pageSpanList[i].popFront();
			//span* kSpan = new span;
			span* kSpan = _pool.myNew();

			kSpan->_n = k;
			kSpan->_pageId = nSpan->_pageId;
			
			nSpan->_n -= k;
			nSpan->_pageId += k;
			
			_pageSpanList[nSpan->_n].pushFront(nSpan);
			// 将nspan的首尾页地址进行存储
			//_idMap[nSpan->_pageId] = nSpan;
			//_idMap[nSpan->_pageId + nSpan->_n - 1] = nSpan;
			_idMap.set(nSpan->_pageId, nSpan);
			_idMap.set(nSpan->_pageId + nSpan->_n - 1, nSpan);

			// 将id和span地址进行映射
			for (PAGE_T i = 0; i < k; ++i) {
				//_idMap[kSpan->_pageId + i] = kSpan;
				_idMap.set(kSpan->_pageId + i, kSpan);
			}

			return kSpan;
		}
	}

	// 重新申请128页span
	//span* newSpan = new span;
	span* newSpan = _pool.myNew();
	void* ptr = systemAlloc(MAX_PAGE - 1);
	newSpan->_pageId = (PAGE_T)ptr >> PAGE_SHIFT;
	newSpan->_n = (MAX_PAGE - 1);

	_pageSpanList[newSpan->_n].pushFront(newSpan);

	return fetchOfPage(k);
}

span* pageCache::getSpanOfId(void* obj) {
	assert(obj);
	//std::unique_lock<std::mutex> lock(_pageMutex);

	PAGE_T id = (PAGE_T)obj >> PAGE_SHIFT;
	span* tmp = (span*)_idMap.get(id);
	assert(tmp);

	return tmp;
}

void pageCache::releasePageCache(span* backSpan) {
	if (backSpan->_n > MAX_PAGE) {
		void* ptr = (void*)(backSpan->_pageId << PAGE_SHIFT);
		systemFree(ptr);
		//delete backSpan;
		_pool.myDelete(backSpan);
	}
	else {
		// 先看是否能合并
		while (1) {
			PAGE_T prevPageId = backSpan->_pageId - 1;
			//auto tmp = _idMap.find(prevPageId);
			span* tmp = (span*)_idMap.get(prevPageId);
			// 前一个span是否存在
			if (tmp == nullptr) {
				break;
			}

			// 是否被使用
			if (tmp->_use) {
				break;
			}

			// 超出128页
			if (tmp->_n + backSpan->_n > 128) {
				break;
			}

			backSpan->_pageId = tmp->_pageId;
			backSpan->_n += tmp->_n;
			_pageSpanList[tmp->_n].erase(tmp);

			//delete tmps;
			_pool.myDelete(tmp);
		}

		while (1) {
			PAGE_T nextPageId = backSpan->_pageId + backSpan->_n;
			span* tmp = (span*)_idMap.get(nextPageId);
			// 后一个span是否存在
			if (tmp == nullptr) {
				break;
			}

			// 是否被使用
			if (tmp->_use) {
				break;
			}

			// 超出128页
			if (tmp->_n + backSpan->_n > 128) {
				break;
			}

			backSpan->_n += tmp->_n;
			_pageSpanList[tmp->_n].erase(tmp);

			//delete tmps;
			_pool.myDelete(tmp);
		}

		//_idMap[backSpan->_pageId] = backSpan;
		//_idMap[backSpan->_pageId + backSpan->_n - 1] = backSpan;
	
		_idMap.set(backSpan->_pageId, backSpan);
		_idMap.set(backSpan->_pageId + backSpan->_n - 1, backSpan);

		_pageSpanList[backSpan->_n].pushFront(backSpan);
		backSpan->_use = false;
	}
}